<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Shop\Controller;

use Admin\Data\Common;
use Doctrine\ORM\EntityManager;
use Laminas\Mvc\I18n\Translator;
use Laminas\View\Model\ViewModel;
use Sales\Entity\Order;
use Sales\Service\OrderManager;
use Sales\Service\OrderStatusManager;
use Shop\Common\ShopCommon;
use Shop\Form\OrderBalancePayForm;
use User\Entity\User;
use User\Entity\UserRecharge;
use User\Service\BalanceLogManager;
use User\Service\UserManager;
use User\Service\UserRechargeManager;

class ReturnController extends HomeActionController
{
    private $translator;
    private $writeEntityManager;
    private $orderManager;
    private $userManager;
    private $balanceLogManager;
    private $orderStatusManager;
    private $userRechargeManager;

    public function __construct(
        Translator      $translator,
        EntityManager   $writeEntityManager,
        OrderManager    $orderManager,
        UserManager     $userManager,
        BalanceLogManager $balanceLogManager,
        OrderStatusManager $orderStatusManager,
        UserRechargeManager $userRechargeManager
    )
    {
        $this->translator           = $translator;
        $this->writeEntityManager   = $writeEntityManager;
        $this->orderManager         = $orderManager;
        $this->userManager          = $userManager;
        $this->balanceLogManager    = $balanceLogManager;
        $this->orderStatusManager   = $orderStatusManager;
        $this->userRechargeManager  = $userRechargeManager;
    }

    /**
     * 支付返回
     * @return \Laminas\Http\Response|ViewModel
     */
    public function orderPaymentReturnAction()
    {
        $orderId    = (int) $this->params()->fromRoute('id', 0);
        $orderInfo  = $this->writeEntityManager->getRepository(Order::class)->findOneBy(['orderId' => $orderId, 'userId' => parent::$userId]);
        if($orderInfo == null) return $this->redirect()->toRoute('shop');

        //当是余额支付，且是未支付状态时，跳转到余额支付进行处理
        if($orderInfo->getPaymentCode() == 'BalancePay' && $orderInfo->getOrderStatus() == $this->shopPlugin()->getOrderStatusCode('WAIT_PAYMENT')) return $this->redirect()->toRoute('shop-return', ['action' => 'orderBalancePay', 'id' => $orderId]);

        $paymentData = ShopCommon::shopPaymentService($orderInfo->getPaymentCode())->orderPaymentReturn($orderInfo);
        $view = new ViewModel();
        if($paymentData['paymentStatus']) {
            //当时在线支付，且只能通过returnNotice判断支付时，进行订单处理
            if ($orderInfo->getPaymentType() == 'OnlinePay' && $orderInfo->getOrderStatus() < $this->shopPlugin()->getOrderStatusCode('WAIT_GOODS_ARRIVE')) {
                $payConfig  = Common::getPaymentConfig($orderInfo->getPaymentCode());
                if ($payConfig['noticeMode'] == 'returnNotice') {
                    $finishPayTime = time();
                    $this->writeEntityManager->beginTransaction();
                    try {
                        $orderInfo = $this->orderManager->editOrder(['orderStatus' => $this->shopPlugin()->getOrderStatusCode('FINISH_PAYMENT'), 'paymentFinishTime' => $finishPayTime], $orderInfo);
                        $this->orderStatusManager->addOrderStatus(['orderStatus' => $orderInfo->getOrderStatus(), 'operateUser' => parent::$userName, 'orderId' => $orderInfo->getOrderId(), 'statusInfo' => $this->translator->translate('订单支付完成'), 'statusTime' => $finishPayTime]);
                        $this->getEventManager()->trigger('shop.order.returnPayFinish.post', $this, ['orderInfo' => $orderInfo]);
                        $this->writeEntityManager->commit();
                    } catch (\Exception $e) {
                        $this->writeEntityManager->rollback();
                        $view->setTemplate('shop/checkout/payment-not-finish');
                    }
                }
            }

            $view->setTemplate('shop/checkout/payment-finish');
        } else $view->setTemplate('shop/checkout/payment-not-finish');

        return $view->setVariables(['orderInfo' => $orderInfo]);
    }

    /**
     * 充值支付返回
     * @return \Laminas\Http\Response|ViewModel
     */
    public function rechargePaymentReturnAction()
    {
        $rechargeId     = (int) $this->params()->fromRoute('id', 0);
        $rechargeInfo   = $this->writeEntityManager->getRepository(UserRecharge::class)->findOneBy(['rechargeId' => $rechargeId]);
        if($rechargeInfo == null) return $this->redirect()->toRoute('shop');

        $paymentData = ShopCommon::shopPaymentService($rechargeInfo->getPayCode())->paymentReturn(['sn' => $rechargeInfo->getPayCode().$rechargeInfo->getAddRechargeTime(), 'currency' => $rechargeInfo->getCurrencyCode(), 'amount' => $rechargeInfo->getRechargeNum(), 'status' => $rechargeInfo->getPayState()]);
        $view = new ViewModel();
        if($paymentData['paymentStatus']) {
            $payConfig  = Common::getPaymentConfig($rechargeInfo->getPayCode());
            if ($payConfig['noticeMode'] == 'returnNotice' && $rechargeInfo->getPayState() < 20) {
                $finishPayTime = time();
                $this->writeEntityManager->beginTransaction();
                try {
                    $rechargeInfo = $this->userRechargeManager->editUserRecharge(['payState' => 20, 'finishRechargeTime' => $finishPayTime], $rechargeInfo);
                    $this->getEventManager()->trigger('shop.recharge.returnPayFinish.post', $this, ['rechargeInfo' => $rechargeInfo]);
                    $this->writeEntityManager->commit();
                } catch (\Exception $e) {
                    $this->writeEntityManager->rollback();
                    $view->setTemplate('shop/return/payment-not-finish');
                }
            }

            $view->setTemplate('shop/return/payment-finish');
        } else $view->setTemplate('shop/return/payment-not-finish');

        return $view->setVariables(['rechargeInfo' => $rechargeInfo]);
    }

    /**
     * 订单余额支付
     * @return \Laminas\Http\Response|string[]
     */
    public function orderBalancePayAction()
    {
        $orderId    = (int) $this->params()->fromRoute('id', 0);
        $orderInfo  = $this->writeEntityManager->getRepository(Order::class)->findOneBy(['orderId' => $orderId, 'userId' => parent::$userId]);
        if($orderInfo == null || $orderInfo->getOrderStatus() > $this->shopPlugin()->getOrderStatusCode('WAIT_PAYMENT')) return $this->redirect()->toRoute('shop');

        $userInfo = $this->writeEntityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);

        $currency = Common::readConfigFile('currency');
        if(!isset($currency[$orderInfo->getCurrencyCode()])) {
            $this->flashMessenger()->addWarningMessage($this->translator->translate('对应订单的货币不存在!'));
            return $this->redirect()->toRoute('home-order', ['action' => 'orderInfo', 'id' => $orderId]);
        }

        $form = new OrderBalancePayForm($userInfo);
        if($this->getRequest()->isPost()) {
            $data = $this->params()->fromPost();
            $form->setData($data);
            if ($form->isValid()) {
                $userMoney      = $userInfo->getUserMoney();
                $orderAmount    = $orderInfo->getOrderAmount();
                if($orderInfo->getCurrencyCode() != $currency['default']['code']) {//货币不同，进行基础货币的转换
                    $orderAmount = number_format($orderAmount/$currency[$orderInfo->getCurrencyCode()]['rate'], 2, '.', '');
                }
                if($orderAmount > $userMoney) {
                    $this->flashMessenger()->addWarningMessage($this->translator->translate('余额不足，不能进行支付!'));
                    return $this->redirect()->toRoute('shop-return', ['action' => 'orderBalancePay', 'id' => $orderId]);
                }

                $finishPayTime = time();
                $userMoney = $userMoney - $orderAmount;
                $this->writeEntityManager->beginTransaction();
                try {
                    $this->balanceLogManager->addBalanceLog([
                        'userId'            => parent::$userId,
                        'userName'          => parent::$userName,
                        'balanceChangeType' => 4,//订单支付
                        'balanceChangeNum'  => '-'.$orderAmount,
                        'balanceChangedAmount' => $userMoney,
                        'balanceChangeTime' => time(),
                        'balanceChangeInfo' => $this->translator->translate('订单编号').'：'.$orderInfo->getOrderSn()
                    ]);
                    $this->userManager->updateUserMoney($userMoney, $userInfo);
                    $orderInfo = $this->orderManager->editOrder(['orderStatus' => $this->shopPlugin()->getOrderStatusCode('FINISH_PAYMENT'), 'paymentFinishTime' => $finishPayTime], $orderInfo);
                    $this->orderStatusManager->addOrderStatus(['orderStatus' => $orderInfo->getOrderStatus(), 'operateUser' => parent::$userName, 'orderId' => $orderInfo->getOrderId(), 'statusInfo' => $this->translator->translate('订单支付完成'), 'statusTime' => $finishPayTime]);

                    $this->getEventManager()->trigger('shop.order.returnPayFinish.post', $this, ['orderInfo' => $orderInfo]);

                    $this->writeEntityManager->commit();
                    return $this->redirect()->toRoute('shop-return', ['action' => 'orderPaymentReturn', 'id' => $orderId]);
                } catch (\Exception $e) {
                    $this->writeEntityManager->rollback();
                    $this->flashMessenger()->addWarningMessage($this->translator->translate('订单支付失败!'));
                    return $this->redirect()->toRoute('home-order', ['action' => 'orderInfo', 'id' => $orderId]);
                }
            }
        }

        return ['orderInfo' => $orderInfo, 'userInfo' => $userInfo, 'currency' => $currency, 'form' => $form];
    }
}